<?php

declare(strict_types=1);

namespace App\Middleware;

use Hyperf\Contract\ConfigInterface;
use Hyperf\Contract\TranslatorInterface;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

class LanguagesMiddleware implements MiddlewareInterface
{
    public function __construct(
        protected ContainerInterface $container,
        protected TranslatorInterface $translator,
        protected ConfigInterface $config
    ) { }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        try {
            $langArr = getFolderNameList($this->config->get('translation.path'));
            $acceptLanguage = $request->getHeader('accept-language');
            if ($acceptLanguage) {
                $acceptLanguageArr = explode(',', current($acceptLanguage));
                $prior = strtr(current($acceptLanguageArr), ['-' => '_']);
                if (false === str_contains($prior, ';') && in_array(strtolower($prior), array_map('strtolower', $langArr))) {
                    $lang = $langArr[array_search(strtolower($prior), array_map('strtolower', $langArr))];
                    $this->translator->setLocale($lang);
                } else {
                    $languageArr = array_map(function ($v){
                        $weight = explode(';', $v);
                        return [
                            'lang' => $weight[0],
                            'q' => explode('=', $weight[1]??null)[1]??null
                        ];
                    }, $acceptLanguageArr);
                    $q = array_column($languageArr, 'q');
                    arsort($q);
                    foreach ($q as $key => $v) {
                        $lang = strtr($languageArr[$key]['lang'], ['-' => '_']);
                        if (in_array(strtolower($lang), array_map('strtolower', $langArr))) {
                            $lang = $langArr[array_search(strtolower($lang), array_map('strtolower', $langArr))];
                            $this->translator->setLocale($lang);
                            break;
                        }
                    }
                }
            }
        } catch (\Throwable $throwable) {}

        return $handler->handle($request);
    }
}
